import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox
import requests
import configparser
import json
import os
from datetime import datetime
import pickle

#接口调试工具， new_golang_websocket_code 文件内工具所有，需要打包
class APIHandlerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("API接口处理工具")
        self.root.geometry("1400x700")  # 增加窗口宽度以容纳右侧响应区
        self.root.minsize(1400, 700)

        # 配置文件处理
        self.config_file = "api_config.ini"
        self.message_history_file = "message_history.pkl"
        self.config = configparser.ConfigParser()
        self.message_history = []
        self.load_config()
        self.load_message_history()

        # 主框架使用网格布局，分为左右两部分
        self.main_frame = ttk.Frame(root, padding="10")
        self.main_frame.pack(fill=tk.BOTH, expand=True)

        # 配置主框架行列权重：左侧40%，右侧60%
        self.main_frame.grid_rowconfigure(0, weight=0)  # 域名区域
        self.main_frame.grid_rowconfigure(1, weight=1)  # 内容区域
        self.main_frame.grid_columnconfigure(0, weight=2)  # 左侧选项卡区域
        self.main_frame.grid_columnconfigure(1, weight=3)  # 右侧响应区域（更宽）

        # 创建域名配置区域（横跨左右）
        self.create_domain_section()

        # 左侧：API接口选项卡区域
        self.create_api_tabs()

        # 右侧：响应显示区域
        self.create_response_area()

    def load_config(self):
        if os.path.exists(self.config_file):
            self.config.read(self.config_file)
        if "Server" not in self.config:
            self.config["Server"] = {"Domain": "http://localhost:8000"}
            self.save_config()

    def save_config(self):
        with open(self.config_file, "w") as f:
            self.config.write(f)

    def load_message_history(self):
        if os.path.exists(self.message_history_file):
            try:
                with open(self.message_history_file, "rb") as f:
                    self.message_history = pickle.load(f)
            except:
                self.message_history = []

    def save_message_history(self):
        try:
            with open(self.message_history_file, "wb") as f:
                pickle.dump(self.message_history, f)
        except Exception as e:
            print(f"保存消息历史失败: {e}")

    def create_domain_section(self):
        """域名配置区域（横跨左右）"""
        domain_frame = ttk.LabelFrame(self.main_frame, text="服务器配置", padding="10")
        domain_frame.grid(row=0, column=0, columnspan=2, sticky="ew", pady=(0, 0))
        domain_frame.grid_columnconfigure(1, weight=1)

        ttk.Label(domain_frame, text="服务器域名:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)

        self.domain_var = tk.StringVar(value=self.config["Server"]["Domain"])
        domain_entry = ttk.Entry(domain_frame, textvariable=self.domain_var)
        domain_entry.grid(row=0, column=1, padx=5, pady=5, sticky="ew")

        save_btn = ttk.Button(domain_frame, text="保存域名", command=self.save_domain)
        save_btn.grid(row=0, column=2, padx=5, pady=5, sticky=tk.W)

    def save_domain(self):
        domain = self.domain_var.get().strip()
        if domain:
            self.config["Server"]["Domain"] = domain
            self.save_config()
            messagebox.showinfo("成功", "域名已保存")
        else:
            messagebox.showerror("错误", "域名不能为空")

    def create_api_tabs(self):
        """左侧：选项卡区域"""
        tab_frame = ttk.Frame(self.main_frame)
        tab_frame.grid(row=1, column=0, sticky="nsew", padx=(0, 10))
        tab_frame.grid_rowconfigure(0, weight=1)
        tab_frame.grid_columnconfigure(0, weight=1)

        tab_control = ttk.Notebook(tab_frame)
        tab_control.grid(row=0, column=0, sticky="nsew")

        # 1. 发送消息接口
        self.send_msg_tab = ttk.Frame(tab_control)
        tab_control.add(self.send_msg_tab, text="发送消息")
        self.create_send_message_tab()

        # 2. 获取连接统计接口
        self.user_count_tab = ttk.Frame(tab_control)
        tab_control.add(self.user_count_tab, text="连接统计")
        self.create_user_count_tab()

        # 3. 获取用户连接详情接口
        self.user_connections_tab = ttk.Frame(tab_control)
        tab_control.add(self.user_connections_tab, text="用户连接详情")
        self.create_user_connections_tab()

        # 4. Redis消费者控制接口
        self.consumer_control_tab = ttk.Frame(tab_control)
        tab_control.add(self.consumer_control_tab, text="消费者控制")
        self.create_consumer_control_tab()

        # 5. Redis消费者状态接口
        self.consumer_status_tab = ttk.Frame(tab_control)
        tab_control.add(self.consumer_status_tab, text="消费者状态")
        self.create_consumer_status_tab()

    def create_send_message_tab(self):
        frame = ttk.LabelFrame(self.send_msg_tab, text="请求参数", padding="10")
        frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        frame.grid_columnconfigure(1, weight=1)
        frame.grid_rowconfigure(4, weight=1)

        # 消息类型选择
        type_frame = ttk.Frame(frame)
        type_frame.grid(row=0, column=0, columnspan=2, padx=5, pady=10, sticky=tk.W)

        ttk.Label(type_frame, text="消息类型:").pack(side=tk.LEFT, padx=5)
        self.message_type_var = tk.StringVar(value="broadcast")

        broadcast_radio = ttk.Radiobutton(
            type_frame,
            text="广播所有人",
            variable=self.message_type_var,
            value="broadcast",
            command=self.update_message_fields
        )
        broadcast_radio.pack(side=tk.LEFT, padx=10)

        data_radio = ttk.Radiobutton(
            type_frame,
            text="指定用户",
            variable=self.message_type_var,
            value="data",
            command=self.update_message_fields
        )
        data_radio.pack(side=tk.LEFT, padx=10)

        # 用户编码
        ttk.Label(frame, text="用户编码:").grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
        self.user_code_var = tk.StringVar()
        self.user_code_entry = ttk.Entry(frame, textvariable=self.user_code_var)
        self.user_code_entry.grid(row=1, column=1, padx=5, pady=5, sticky="ew")

        # 用户密钥
        ttk.Label(frame, text="用户Key:").grid(row=2, column=0, padx=5, pady=5, sticky=tk.W)
        self.user_key_var = tk.StringVar()
        self.user_key_entry = ttk.Entry(frame, textvariable=self.user_key_var)
        self.user_key_entry.grid(row=2, column=1, padx=5, pady=5, sticky="ew")

        # 服务器密码
        ttk.Label(frame, text="服务器密码:").grid(row=3, column=0, padx=5, pady=5, sticky=tk.W)
        self.server_password_var = tk.StringVar(value="")
        ttk.Entry(frame, textvariable=self.server_password_var).grid(row=3, column=1, padx=5, pady=5, sticky="ew")

        # 消息内容
        msg_frame = ttk.Frame(frame)
        msg_frame.grid(row=4, column=0, columnspan=2, padx=5, pady=5, sticky="nsew")
        msg_frame.grid_rowconfigure(1, weight=1)
        msg_frame.grid_columnconfigure(0, weight=1)

        ttk.Label(msg_frame, text="消息内容 (JSON格式):").grid(row=0, column=0, sticky=tk.W)

        msg_content_frame = ttk.Frame(msg_frame)
        msg_content_frame.grid(row=1, column=0, sticky="nsew")

        self.message_var = scrolledtext.ScrolledText(msg_content_frame, wrap=tk.WORD)
        self.message_var.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.message_var.insert(tk.END, '{"content": "Hello World"}')

        # 历史消息按钮
        history_frame = ttk.Frame(msg_content_frame, width=100)
        history_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=5)

        ttk.Button(history_frame, text="历史消息", command=self.show_history_messages).pack(pady=5, fill=tk.X)
        ttk.Button(history_frame, text="清除历史", command=self.clear_history_messages).pack(pady=5, fill=tk.X)

        # 发送按钮
        send_btn = ttk.Button(frame, text="发送消息", command=self.send_message)
        send_btn.grid(row=5, column=0, columnspan=2, pady=10)

        self.update_message_fields()

    def update_message_fields(self):
        msg_type = self.message_type_var.get()
        if msg_type == "broadcast":
            self.user_code_entry.config(state=tk.DISABLED)
            self.user_key_entry.config(state=tk.DISABLED)
        else:
            self.user_code_entry.config(state=tk.NORMAL)
            self.user_key_entry.config(state=tk.NORMAL)

    def show_history_messages(self):
        if not self.message_history:
            messagebox.showinfo("提示", "没有历史消息")
            return

        history_window = tk.Toplevel(self.root)
        history_window.title("选择历史消息")
        history_window.geometry("1000x600")
        history_window.transient(self.root)
        history_window.grab_set()

        listbox = tk.Listbox(history_window, selectmode=tk.SINGLE)
        listbox.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        for i, (timestamp, msg_type, content) in enumerate(self.message_history):
            display_text = f"[{timestamp}] {msg_type}: {json.dumps(content)}"
            listbox.insert(tk.END, display_text)

        def select_message():
            selection = listbox.curselection()
            if selection:
                index = selection[0]
                _, msg_type, content = self.message_history[index]
                self.message_type_var.set(msg_type)
                self.update_message_fields()

                if msg_type == "data":
                    self.user_code_var.set(content.get("userCode", ""))
                    self.user_key_var.set(content.get("userKey", ""))

                self.server_password_var.set(content.get("serverPassword", ""))
                self.message_var.delete("1.0", tk.END)
                self.message_var.insert(tk.END, json.dumps(content.get("message", {}), indent=2))

                history_window.destroy()

        ttk.Button(history_window, text="选择", command=select_message).pack(pady=10)

    def clear_history_messages(self):
        if messagebox.askyesno("确认", "确定要清除所有历史消息吗？"):
            self.message_history = []
            self.save_message_history()
            messagebox.showinfo("提示", "历史消息已清除")

    def create_user_count_tab(self):
        frame = ttk.LabelFrame(self.user_count_tab, text="请求参数", padding="10")
        frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        ttk.Label(frame, text="获取当前连接的用户数量，无需参数。").pack(pady=10, anchor=tk.W)
        get_btn = ttk.Button(frame, text="获取连接统计", command=self.get_user_count)
        get_btn.pack(pady=10)

    def create_user_connections_tab(self):
        frame = ttk.LabelFrame(self.user_connections_tab, text="请求参数", padding="10")
        frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        frame.grid_columnconfigure(1, weight=1)

        ttk.Label(frame, text="服务器密码:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
        self.connections_password_var = tk.StringVar(value="")
        ttk.Entry(frame, textvariable=self.connections_password_var).grid(row=0, column=1, padx=5, pady=5, sticky="ew")

        get_btn = ttk.Button(frame, text="获取用户连接详情", command=self.get_user_connections)
        get_btn.grid(row=1, column=0, columnspan=2, pady=10)

    def create_consumer_control_tab(self):
        frame = ttk.LabelFrame(self.consumer_control_tab, text="请求参数", padding="10")
        frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        ttk.Label(frame, text="选择操作:").pack(anchor=tk.W, pady=(10, 5))

        self.consumer_action_var = tk.StringVar(value="start")
        action_frame = ttk.Frame(frame)
        action_frame.pack(anchor=tk.W, pady=5)

        ttk.Radiobutton(action_frame, text="启动消费者", variable=self.consumer_action_var, value="start").pack(
            side=tk.LEFT, padx=10)
        ttk.Radiobutton(action_frame, text="停止消费者", variable=self.consumer_action_var, value="stop").pack(
            side=tk.LEFT, padx=10)

        control_btn = ttk.Button(frame, text="执行操作", command=self.control_consumer)
        control_btn.pack(pady=10)

    def create_consumer_status_tab(self):
        frame = ttk.LabelFrame(self.consumer_status_tab, text="请求参数", padding="10")
        frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        ttk.Label(frame, text="获取当前Redis消费者的状态信息，无需参数。").pack(pady=10, anchor=tk.W)
        get_btn = ttk.Button(frame, text="获取消费者状态", command=self.get_consumer_status)
        get_btn.pack(pady=10)

    def create_response_area(self):
        """右侧：响应显示区域（更宽）"""
        response_frame = ttk.LabelFrame(self.main_frame, text="响应结果", padding="10")
        response_frame.grid(row=1, column=1, sticky="nsew")
        response_frame.grid_rowconfigure(1, weight=1)
        response_frame.grid_columnconfigure(0, weight=1)

        # 添加清除响应按钮
        btn_frame = ttk.Frame(response_frame)
        btn_frame.grid(row=0, column=0, sticky="ew", pady=(0, 5))
        ttk.Button(btn_frame, text="清除响应记录", command=self.clear_response).pack(side=tk.RIGHT)

        # 响应文本区域
        self.response_text = scrolledtext.ScrolledText(
            response_frame,
            wrap=tk.WORD,
            font=("Consolas", 10)
        )
        self.response_text.grid(row=1, column=0, sticky="nsew")
        self.response_text.config(state=tk.DISABLED)

        # 确保响应区域能拉伸
        response_frame.grid_rowconfigure(1, weight=1)

    def clear_response(self):
        """清除响应区域内容"""
        self.response_text.config(state=tk.NORMAL)
        self.response_text.delete("1.0", tk.END)
        self.response_text.config(state=tk.DISABLED)

    def log_response(self, message):
        self.response_text.config(state=tk.NORMAL)
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.response_text.insert(tk.END, f"[{timestamp}]\n{message}\n\n")
        self.response_text.see(tk.END)
        self.response_text.config(state=tk.DISABLED)

    def send_request(self, method, endpoint, params=None, json_data=None):
        try:
            domain = self.domain_var.get().strip().rstrip('/')
            url = f"{domain}{endpoint}"

            self.log_response(f"请求: {method} {url}")
            if params:
                self.log_response(f"参数: {json.dumps(params, ensure_ascii=False, indent=2)}")
            if json_data:
                self.log_response(f"请求体: {json.dumps(json_data, ensure_ascii=False, indent=2)}")

            # 发送请求
            if method.upper() == "GET":
                response = requests.get(url, params=params, timeout=15)
            elif method.upper() == "POST":
                response = requests.post(url, json=json_data, timeout=15)
            else:
                raise ValueError(f"不支持的HTTP方法: {method}")

            # 处理所有状态码的响应，包括400
            try:
                result = response.json()
                self.log_response(f"响应 ({response.status_code}):\n{json.dumps(result, ensure_ascii=False, indent=2)}")
                return response.status_code < 400, result
            except json.JSONDecodeError:
                self.log_response(f"响应 ({response.status_code}):\n{response.text}")
                return response.status_code < 400, None

        except requests.exceptions.RequestException as e:
            # 提取HTTP错误响应内容（包括400等状态码）
            error_msg = str(e)
            if hasattr(e, 'response') and e.response is not None:
                try:
                    err_response = e.response.json()
                    error_msg += f"\n响应内容: {json.dumps(err_response, ensure_ascii=False, indent=2)}"
                except:
                    error_msg += f"\n响应内容: {e.response.text}"
            self.log_response(f"请求错误: {error_msg}")
            return False, None
        except Exception as e:
            self.log_response(f"错误: {str(e)}")
            return False, None

    def send_message(self):
        msg_type = self.message_type_var.get()
        user_code = self.user_code_var.get().strip()
        user_key = self.user_key_var.get().strip()
        server_password = self.server_password_var.get().strip()
        message = self.message_var.get("1.0", tk.END).strip()

        if not server_password:
            messagebox.showerror("错误", "服务器密码不能为空")
            return

        if not message:
            messagebox.showerror("错误", "消息内容不能为空")
            return

        try:
            message_json = json.loads(message)
        except json.JSONDecodeError as e:
            messagebox.showerror("错误", f"消息内容不是有效的JSON格式:\n{e}")
            return

        payload = {
            "serverPassword": server_password,
            "type": msg_type,
            "message": message_json
        }

        if msg_type == "data":
            if not user_code:
                messagebox.showerror("错误", "指定用户时，用户编码不能为空")
                return
            if not user_key:
                messagebox.showerror("错误", "指定用户时，用户Key不能为空")
                return
            payload["userCode"] = user_code
            payload["userKey"] = user_key
        else:
            payload["user_code"] = ""

        success, response = self.send_request("POST", "/send-message", json_data=payload)

        if success:
            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            history_item = (timestamp, msg_type, payload.copy())
            self.message_history.append(history_item)
            if len(self.message_history) > 50:
                self.message_history = self.message_history[-50:]
            self.save_message_history()

    def get_user_count(self):
        self.send_request("GET", "/user-count")

    def get_user_connections(self):
        server_password = self.connections_password_var.get().strip()

        if not server_password:
            messagebox.showerror("错误", "服务器密码不能为空")
            return

        params = {"server_password": server_password}
        self.send_request("GET", "/user-connections", params=params)

    def control_consumer(self):
        action = self.consumer_action_var.get()
        self.send_request("GET", f"/control-consumer?action={action}")

    def get_consumer_status(self):
        self.send_request("GET", "/consumer-status")


if __name__ == "__main__":
    root = tk.Tk()
    app = APIHandlerApp(root)
    root.mainloop()